home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gigarom 1
/
Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso
/
FILES
/
DEV
/
C-H
/
CHexDmpDA.cpt
/
Hex Dump DA
/
main.HexDumpDA.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-06-15
|
10KB
|
462 lines
/*
* main.HexDumpDA.c
*
* HexDump is a DA that displays the contents of a file in hex and ASCII,
* intended as an example of how to write a desk accessory. Among other
* things, it shows the structure of a DA, how a DA gets and responds to
* events, and how a DA manages the menu bar.
*
* Steve Stein, Symantec Corp.
*
*/
#include <DeviceMgr.h>
#include <WindowMgr.h>
#include <MenuMgr.h>
#include <EventMgr.h>
#include <FileMgr.h>
#include <ToolboxUtil.h>
#include <StdFilePkg.h>
#include <pascal.h>
#include "HexDump.h"
/* global variables */
int already_open = 0; /* 1 -> DA is already open */
DCtlPtr dce; /* device control entry */
MenuHandle menu = 0L; /* handle for our menu */
int menuID; /* our menu ID */
WindowPtr wp = 0L; /* our window pointer */
Cursor wait; /* a copy of the watch cursor */
extern int fileRef; /* the refnum of the file we're showing */
extern long fileSize; /* and the file's size (in bytes) */
enum fork whichFork; /* which fork are we viewing? */
extern Handle findBufH;
/*
* main program
*
* The first two arguments are the values passed in registers A0/A1
* to an assembly-language desk accessory. The third argument is a
* selector indicating which entry point was called.
*
* No assembly language is needed to write a desk accessory in
* LightspeedC!
*
*/
main(p, d, n)
cntrlParam *p; /* ==> parameter block */
DCtlPtr d; /* ==> device control entry */
int n; /* entry point selector */
{
/* if dCtlStorage is nil then our storage wasn't allocated... */
if (d->dCtlStorage == 0) { /* we must abort */
if (n == 0) { /* if request is "open" */
SysBeep(3); /* beep, then close the DA */
CloseDriver(d->dCtlRefNum);
}
return(0); /* goodbye */
}
dce = d; /* copy the DCE ptr into our globals */
dce->dCtlFlags &= ~dCtlEnable; /* we are not re-entrant */
switch (n) { /* handle request: */
case 0: /* open */
doOpen();
break;
case 2: /* control */
doControl(p->csCode, p->csParam);
break;
case 4: /* close */
doClose();
break;
default: ;
}
dce->dCtlFlags |= dCtlEnable; /* enable control calls once more */
return(0); /* we are done */
}
/*
* doOpen - initialize DA
*
* This routine is called each time the DA is selected from the Apple
* menu, even if it is already open. We need to make sure to go
* through our initialization the first time only, so we use a (global)
* flag "already_open" to keep track.
*
* However, the Device Manager resets the "dCtlFlags", "dCtlMenu",
* "dCtlDelay", and "dCtlEMask" fields of the device control entry
* from the corresponding fields of the device header each time the
* desk accessory is opened, EVEN IF IT ALREADY OPEN. Therefore we
* must set these fields to their proper values each time.
*
* We have to set the dNeedGoodBye flag so that we can close the file
* we're viewing if the application quits out from under us.
*/
doOpen()
{
/* every time ... */
dce->dCtlFlags |= dNeedLock|dNeedGoodBye;
if (wp)
SelectWindow(wp); /* bring our window front */
if (already_open) {
dce->dCtlMenu = menuID; /* set the menu id */
return;
}
/* first time only ... */
/* do some global initialization */
/* Create our menu */
/* Create our window */
/* Open a file */
Get_Wait_Cursor();
already_open = 1;
Create_Menu();
Create_Window();
HiliteMenu( dce->dCtlMenu ); /* to simulate "open" menu selection */
if (!doOpenFile()) { /* if user cancels, close HexDump */
CloseDriver(dce->dCtlRefNum); /* Quit */
return;
};
HiliteMenu(0);
if (!Init_Find()) /* Init_Find will fail if there's not */
/* enough memory for the find buffer */
Disable_Find();
}
/*
* doControl - handle DA actions
*
* This routine handles the DA actions that may be required. This
* DA must respond to two control actions: menu selections and events.
* In addition, this routine can also handle the "goodbye kiss" when
* the application quits out from under the DA.
*
*/
doControl(code, parm)
int code;
int *parm;
{
switch (code) {
case accMenu:
doMenu(parm[1]);
break;
case accEvent:
doEvent(*((EventRecord **)parm));
break;
case goodBye:
doGoodBye();
break;
default: ;
}
if (code != accCursor) Update_Menu_Bar();
}
/*
* doClose - clean up before being closed
*
*/
doClose()
{
Close_File( fileRef );
DisposHandle( findBufH );
DeleteMenu(dce->dCtlMenu);
DrawMenuBar();
dce->dCtlMenu = 0;
DisposeMenu(menu);
Destroy_Window();
}
/* Menu maintenance routines: */
/*
* Create_Menu
*
* Get our menu from the resource file, set dce->dCtlMenu,
* insert the menu into the menu bar and draw the menu bar.
*/
static
Create_Menu()
{
dce->dCtlMenu = menuID = OwnedResourceID( MENUID );
menu = GetMenu(menuID);
(**menu).menuID = menuID;
InsertMenu(menu = GetMenu(menuID), 0);
DrawMenuBar();
}
/*
* Update_Menu_Bar - Manage the appearance of our menu in the menu bar
*
* Our menu should appear when the front window belongs to us.
*/
static
Update_Menu_Bar()
{
register WindowPeek wPtr = (WindowPeek) FrontWindow ();
if (wPtr) { /* there should always be a window, but we'll check. */
if ( wPtr->windowKind == dce->dCtlRefNum ) {
if (!GetMHandle (dce->dCtlMenu)) {
InsertMenu (menu, 0);
DrawMenuBar ();
}
}
else if (GetMHandle (dce->dCtlMenu)) {
DeleteMenu (dce->dCtlMenu);
DrawMenuBar ();
}
}
}
static
Disable_Find()
{
/* we had no memory for the find buffer */
DisableItem(menu, FIND);
DisableItem(menu, FINDAGAIN);
}
static
Set_Fork(option)
enum fork option;
{
whichFork = option;
if (option==data) {
CheckItem( menu, DATAFORK, true );
CheckItem( menu, RSRCFORK, false );
}
else {
CheckItem( menu, DATAFORK, false );
CheckItem( menu, RSRCFORK, true );
}
}
/*
* doMenu - process menu selection
*
*/
doMenu(i) /* the i-th menu item was selected */
int i;
{
switch (i) {
case ABOUT: doAbout(); break;
case OPEN: doOpenFile(); break;
case DUMPTO: doDumpTo(); break;
case DATAFORK: doOpenFork( data ); break;
case RSRCFORK: doOpenFork( resource ); break;
case FIND: doFind(); break;
case FINDAGAIN: doFindAgain(); break;
case GOTO: doGoto(); break;
case QUIT:
CloseDriver(dce->dCtlRefNum); /* close down the DA */
return;
}
HiliteMenu(0);
}
static
doOpenFork( f )
enum fork f;
{
int newFileRef;
if (f!=whichFork) {
if (Open_Fork(f, &newFileRef)) {
New_Open_File( newFileRef );
Set_Fork(f);
}
else
ErrorStr("\pCan't open fork.");
}
}
static
doOpenFile()
{
char *fileName;
int vRef;
enum fork option;
int newFileRef;
do {
if (!oldfilename(&option ))
return 0;
} while (!Open_Fork(option, &newFileRef));
New_Open_File( newFileRef );
Set_Fork(option);
return 1;
}
/*
* TestWindowRgn uses the window's WDEF proc to sort out mouse hits.
* In an application, FindWindow does this for you. In a DA, you
* must do it yourself.
*/
static
Boolean TestWindowRgn(wp,p,msg)
WindowPtr wp;
Point p;
int msg;
{
ProcPtr wDef;
wDef = (ProcPtr) *((WindowPeek)wp) -> windowDefProc;
return(CallPascalL( 8, wp, (int) wHit, p, wDef )==msg);
}
doMouse(p)
Point p;
{
if (TestWindowRgn(wp, p, wInGrow))
doGrow(p);
else if (TestWindowRgn(wp, p, wInZoomIn))
doZoom(p, inZoomIn);
else if (TestWindowRgn(wp, p, wInZoomOut))
doZoom(p, inZoomOut);
else
doScrollControl(p);
}
doCmdKey(c)
char c;
{
int code;
switch (c) {
case 'o':
case 'O': code = OPEN; break;
case 'd':
case 'D': code = DUMPTO; break;
case 'f':
case 'F': code = FIND; break;
case 'a':
case 'A': code = FINDAGAIN; break;
case 'g':
case 'G': code = GOTO; break;
case 'q':
case 'Q': code = QUIT; break;
default : SysBeep(10); return;
}
HiliteMenu( dce->dCtlMenu );
doMenu( code );
}
/*
* doEvent is the DA's event handler.
*/
doEvent(e)
EventRecord *e;
{
switch (e->what) {
case updateEvt:
doUpdate();
break;
case mouseDown:
doMouse(e->where);
break;
case activateEvt:
doActivate((Boolean)(e->modifiers & activeFlag));
break;
case keyDown:
case autoKey:
if ( e->modifiers & cmdKey )
doCmdKey((char)(e->message & charCodeMask));
else
SysBeep(10);
break;
}
}
/*
* doGoodBye - respond to "goodbye kiss"
*
* This is called by the system when the application quits while
* the DA is still open. We need to close our file, so we have
* requested a "goodbye kiss".
*
*/
doGoodBye()
{
Close_File(fileRef);
}
/* error handling: */
ErrorStr(s)
char *s;
{
ParamText(s,"","","");
Alert( OwnedResourceID(ERROR_ALERT), 0L );
doUpdate();
}
Error(err)
{
Str255 s;
NumToString(err,s);
ParamText("\pHexDump detected error, ID = ",s,"","");
Alert( OwnedResourceID(ERROR_ALERT), 0L);
doUpdate();
}
No_Error(err)
{
if (err==noErr) return true;
Error(err);
return false;
}
/* utility routines: */
/* OwnedResourceID - Compute the resource ID of */
/* a resource owned by this DA. */
OwnedResourceID(n)
{
return( 0xC000 + ((~(dce->dCtlRefNum))<<5) + n );
}
/* Get_Wait_Cursor -
* Load the variable "wait" with the watch cursor.
* Dispose the resource's copy in memory if it wasn't already there.
*/
Get_Wait_Cursor()
{
CursHandle h;
Boolean dispose;
SetResLoad(false);
h = GetCursor(watchCursor);
dispose = (GetHandleSize((Handle)h) == 0);
SetResLoad(true);
BlockMove(*(h=GetCursor(watchCursor)), &wait, sizeof( Cursor ));
if (dispose) ReleaseResource((Handle)h);
}